#include "Vector3.h"
#include <algorithm>
#include <math.h>

namespace soft_renderer
{
	Vector3::Vector3(double x, double y, double z)
	{
		data[0] = x;
		data[1] = y;
		data[2] = z;
	}

	void Vector3::set(double x, double y, double z)
	{
		data[0] = x;
		data[1] = y;
		data[2] = z;
	}

	void Vector3::setScalar(double scalar)
	{
		data[0] = scalar;
		data[1] = scalar;
		data[2] = scalar;
	}

	void Vector3::setX(double x)
	{
		data[0] = x;
	}

	void Vector3::setY(double y)
	{
		data[1] = y;
	}

	void Vector3::setZ(double z)
	{
		data[2] = z;
	}

	void Vector3::copy(const Vector3& v)
	{
		data[0] = v.data[0];
		data[1] = v.data[1];
		data[2] = v.data[2];
	}

	double Vector3::x()
	{
		return data[0];
	}

	double Vector3::y()
	{
		return data[1];
	}

	double Vector3::z()
	{
		return data[2];
	}

	void Vector3::add(const Vector3& v)
	{
		data[0] += v.data[0];
		data[1] += v.data[1];
		data[2] += v.data[2];
	}

	void Vector3::addVectors(const Vector3& a, const Vector3& b)
	{
		data[0] = a.data[0] + b.data[0];
		data[1] = a.data[1] + b.data[1];
		data[2] = a.data[2] + b.data[2];
	}

	void Vector3::sub(const Vector3& v)
	{
		data[0] -= v.data[0];
		data[1] -= v.data[1];
		data[2] -= v.data[2];
	}

	void Vector3::subVectors(const Vector3& a, const Vector3& b)
	{
		data[0] = a.data[0] - b.data[0];
		data[1] = a.data[1] - b.data[1];
		data[2] = a.data[2] - b.data[2];
	}

	void Vector3::divideScalar(double scalar)
	{
		multiplyScalar(1.0 / scalar);
	}

	void Vector3::multiplyScalar(double scalar)
	{
		data[0] *= scalar;
		data[1] *= scalar;
		data[2] *= scalar;
	}

	void Vector3::crossVectors(const Vector3& a, const Vector3& b)
	{
		data[0] = a.data[1] * b.data[2] - a.data[2] * b.data[1];
		data[1] = a.data[2] * b.data[0] - a.data[0] * b.data[2];
		data[2] = a.data[0] * b.data[1] - a.data[1] * b.data[0];
	}

	//void Vector3::applyMatrix4(Matrix4& m)
	//{
	//	applyMatrix4(m);
	//}

	void Vector3::applyMatrix4(const Matrix4& m)
	{
		// V' = M * V
		// V为列向量
		const double x = data[0];
		const double y = data[1];
		const double z = data[2];

		const double* e = m.data;
		const double w = 1.0 / (e[12] * x + e[13] * y + e[14] * z + e[15]);

		data[0] = (e[0] * x + e[1] * y + e[2] * z + e[3]) * w;
		data[1] = (e[4] * x + e[5] * y + e[6] * z + e[7]) * w;
		data[2] = (e[8] * x + e[9] * y + e[10] * z + e[11]) * w;
	}

	double Vector3::lengthSq()
	{
		return data[0] * data[0] + data[1] * data[1] + data[2] * data[2];
	}

	double Vector3::length()
	{
		return sqrt(lengthSq());
	}

	void Vector3::normalize()
	{
		divideScalar(length());
	}

	Vector3 Vector3::negated()
	{
		return Vector3(-data[0], -data[1], -data[2]);
	}

	double Vector3::dot(const Vector3& v) const
	{
		return data[0] * v.data[0] + data[1] * v.data[1] + data[2] * v.data[2];
	}

}





